package com.lagou.rpc.consumer.proxy;

import com.alibaba.fastjson.JSON;
import com.lagou.rpc.api.IUserService;
import com.lagou.rpc.common.RpcRequest;
import com.lagou.rpc.common.RpcResponse;
import com.lagou.rpc.config.ZooConfig;
import com.lagou.rpc.consumer.client.RpcClient;
import com.lagou.rpc.consumer.tool.ZkCli;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 客户端代理类-创建代理对象
 * 1.封装request请求对象
 * 2.创建RpcClient对象
 * 3.发送消息
 * 4.返回结果
 */
public class RpcClientProxy {

    static Map<String, Object> rpcClientMap = new ConcurrentHashMap<>();

    //定义一个计数器
    public static int count = 0;

    public static void initRpcClient(Map<String, String> serverCountMap) {
        if (serverCountMap.size() > 0) {
            Set<Map.Entry<String, String>> entries = serverCountMap.entrySet();
            for (Map.Entry<String, String> entry : entries) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (value != null) {
                    String[] split = value.split("#");
                    String ip = split[0];
                    int port = Integer.valueOf(split[1]);
                    RpcClient rpcClient = new RpcClient(ip, port);
                    rpcClientMap.put(key, rpcClient);
                }
            }
        }
    }

    public static void getOneRpcClient(String node, String value) {
        if (value != null) {
            String[] split = value.split("#");
            String ip = split[0];
            int port = Integer.valueOf(split[1]);
            RpcClient rpcClient = new RpcClient(ip, port);
            rpcClientMap.put(node, rpcClient);
        }
    }

    public static void removeRpcClient(String key) {
        RpcClient rpcClient = (RpcClient) rpcClientMap.get(key);
        rpcClient.close();
        rpcClientMap.remove(key);
    }

    public static IUserService getProxy() {
        IUserService proxy = (IUserService) createProxy(IUserService.class);
        return proxy;
    }

    public static RpcClient getConnect() {
        //获取相应时间短的服务器进行调用
        String key = ZkCli.getMinimumResponseTime();
        System.out.println("最短响应时间的服务器是： " + key);
        if (key != null) {
            RpcClient rpcClient = (RpcClient) rpcClientMap.get(key);
            return rpcClient;
        } else {
            if (rpcClientMap.size() > 0) {
                String[] keys = rpcClientMap.keySet().toArray(new String[0]);
                Random random = new Random();
                String key1 = keys[random.nextInt(keys.length)];
                RpcClient rpcClient = (RpcClient) rpcClientMap.get(key1);
                System.out.println("当前连接的服务器地址是：" + key1);
                return rpcClient;
            }
        }
        return null;
    }

    /**
     * 轮询获取RpcClient对象
     *
     * @return
     */
    private static RpcClient getRpcClient() {
        //轮询处理 （当计数器的大小 等于 初始化的ip的大小的时候 复位0）
        if (count >= 2) {
            count = 0;
        }
        //轮询获取 0-1 2=2 count =0
        RpcClient rpcClient = null;
        if (count == 0) {
            rpcClient = new RpcClient("127.0.0.1", 8866);
        }
        if (count == 1) {
            rpcClient = new RpcClient("127.0.0.1", 8877);
        }
        count++;
        return rpcClient;
    }

    public static Object createProxy(Class serviceClass) {
        long start = System.currentTimeMillis();
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                new Class[]{serviceClass}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) {
                        //1.封装request请求对象
                        RpcRequest rpcRequest = new RpcRequest();
                        rpcRequest.setRequestId(UUID.randomUUID().toString());
                        rpcRequest.setClassName(method.getDeclaringClass().getName());
                        rpcRequest.setMethodName(method.getName());
                        rpcRequest.setParameterTypes(method.getParameterTypes());
                        rpcRequest.setParameters(args);
                        //2.创建RpcClient对象
                        RpcClient rpcClient = getConnect();
                        if (rpcClient == null) {
                            System.out.println("当前无可连接的服务器");
                            return null;
                        }
                        try {
                            //3.发送消息
                            Object responseMsg = rpcClient.send(JSON.toJSONString(rpcRequest));
                            RpcResponse rpcResponse = JSON.parseObject(responseMsg.toString(), RpcResponse.class);
                            if (rpcResponse.getError() != null) {
                                throw new RuntimeException(rpcResponse.getError());
                            }
                            //4.返回结果
                            Object result = rpcResponse.getResult();
                            String ip = rpcClient.getIp();
                            int port = rpcClient.getPort();
                            if(port == ZooConfig.port01){
                                Thread.sleep(2000);
                            }
                            if(port == ZooConfig.port02){
                                Thread.sleep(3000);
                            }
                            long end = System.currentTimeMillis();
                            ZkCli.setNodeValue(ip + "#" + port, start, end);
                            return JSON.parseObject(result.toString(), method.getReturnType());
                        } catch (Exception e) {
                            throw new RuntimeException(e.getMessage());
                        } finally {
//                            rpcClient.close();
                        }
                    }
                });
    }
}
